package resp

import (
	"errors"
	"fly/schema"
	"github.com/jinzhu/copier"
	"time"
)

type BaseModelResp struct {
	CreateTime  int64  `json:"createTime" description:"创建时间"`
	UpdateTime  int64  `json:"updateTime" description:"更新时间"`
	CreatorName string `json:"creatorName" description:"创建人员"`
	UpdaterName string `json:"UpdaterName" description:"更新人员"`
}

type StatusResult struct {
	Code    int               `json:"code"`
	Status  schema.StatusText `json:"status"`
	TraceId string            `json:"traceId"`
	Content *interface{}      `json:"content,omitempty"`
	Message string            `json:"message,omitempty"`
}

type ListResult struct {
	List interface{} `json:"list"`
}

type PaginationResult struct {
	List     interface{} `json:"list"`
	Total    int         `json:"total"`
	Current  int         `json:"current"`
	PageSize int         `json:"pageSize"`
}

type TreeNode interface {
	GetPId() int64
	GetId() int64
	GetSort() int
	AddChildren(children TreeNode)
}

func FindInsert(node TreeNode, children []TreeNode) int {
	low, high := 0, len(children)-1
	for low <= high {
		mid := (low + high) / 2
		if node.GetSort() > children[mid].GetSort() {
			low = mid + 1
		} else {
			high = mid - 1
		}
	}
	return low
}

func NodeList2Tree(list []TreeNode) []TreeNode {
	if list == nil || len(list) == 0 {
		return list
	}

	nodeMap := make(map[int64]TreeNode)
	var rootNodes []TreeNode
	for _, item := range list {
		id := item.GetId()
		nodeMap[id] = item
	}
	for _, node := range nodeMap {
		if parent, found := nodeMap[node.GetPId()]; found {
			parent.AddChildren(node)
		} else {
			//rootNodes = append(rootNodes, node)
			// 二分查找合适的位置
			low := FindInsert(node, rootNodes)
			// 插入节点
			rootNodes = append(rootNodes[:low], append([]TreeNode{node}, rootNodes[low:]...)...)
		}
	}
	return rootNodes
}

// Copy2TimeResp 复制属性并转换time->int64
func Copy2TimeResp(toValue interface{}, fromValue interface{}) (err error) {
	return copier.CopyWithOption(toValue, fromValue, copier.Option{IgnoreEmpty: true, DeepCopy: true, Converters: []copier.TypeConverter{
		{
			SrcType: time.Time{},
			DstType: int64(0),
			Fn: func(src interface{}) (dst interface{}, err error) {
				s, ok := src.(time.Time)
				if ok {
					return s.UnixMilli(), nil
				}
				return 0, errors.New("not time type")
			},
		},
	}})
}
